/* jshint esversion: 6 */
console.log('%c Pet-Script %c 脚本解析器\n %c作者: 小瑞猫',
    'font-family: "Helvetica Neue",Helvetica, Arial, sans-serif;font-size:64px;color:#FFB6C1;-webkit-text-fill-color:#FFB6C1;-webkit-text-stroke: 1px #FFB6C1;',
    'font-size:25px;color:#FFB6C1;', 'font-size:15px;color:#FFB6C1;');
/**
 * 2.0 版本的脚本解析
 */
function PetScript() {
    var $this = this;
    // 解析定义类列表 (GetResolve 函数得到)
    this.ResolveList = [];
    // 变量链
    this.VariableChain = {};
    /**
     * 解析脚本
     */
    this.Parse = function (text) {
        var $ = {};
        // 解析信息
        $.site = 0; // 解析位置
        $.script = text; // 脚本信息
        // 解析结果链
        $.Chain = [];
        // 开始解析
        $this.ParseBlock($);
        $.site = 0;
        $this.ParseOperator($);
        $.site = 0;
        $this.ParsePriority($);
        $.site = 0;
        $this.ParsingAlayer($.Chain);
        return $;
    };
};
/**
 * 解析器功能实现
 *  块定义
 *      { }    范围约束内部数据不解析
 *      ( )    块约束内部数据解析
 *      [,]    数组数据分好进行数据分割
 *  文本标记
 *      "" '' ``
 *  注释
 *      块注释
 *  运算符
 *      + - * / 
 *  调用符
 *      .       处理实现但无效
 *  标记符
 *      ; \n 空格 
 */
PetScript.prototype = {
    /**
     * 初始化默认定义
     */
    InitDefault: function () {
        var $ = this;
        /**
         * 块定义
         */
        var Block = this.SetBlock("{", "}", function (course, N) {
            // 取消递归
            return false;
        });
        Block.Recursive = false;
        Block.PerformProcessing = function (course, N) {
            course[N] = Object.assign(course[N].Chain[0], { Types: "Block" });
        };
        /**
         * 限定范围
         */
        this.SetBlock("(", ")").PerformProcessing = function (course, N) {
            course[N] = Object.assign(course[N].Chain, { Types: "Scope" });
        };
        /**
         * 数组定义
         */
        this.SetBlock("[", "]", function (course, N) {
            var Chain = course[N].Chain, cha = [];
            for (let i = 0; i < Chain.length; i++) {
                if (typeof Chain[i] == "string") {
                    cha = [...cha, ...Chain[i].split(',')];
                } else if (Chain[i] != '' && Chain[i] != null && typeof (Chain[i]) != undefined) {
                    cha.push(Chain[i]);
                }
            }
            course[N].Chain = cha;
            return true;
        }).PerformProcessing = function (course, N) {
            course[N] = Object.assign(course[N].Chain, { Types: "Array" });
        };
        /**
         * 文本标记
         */
        var text = function (course, N) {
            course[N] = Object.assign(course[N].Chain[0], { Types: "String" });
        };
        this.SetBlock('"', '"', text).Recursive = false;
        this.SetBlock("'", "'", text).Recursive = false;
        this.SetBlock("`", "`", text).Recursive = false;
        // 注释
        this.SetBlock("/*", "*/", function (course, N) {
            // 删除注释内容
            course.splice(N, 1);
            // 取消递归
            return false;
        }).Recursive = false;
        // 运算符
        let oper_jian = this.SetOperator("-");
        oper_jian.Priority = 3;
        oper_jian.ParseHandler = function (course, N) {
            let filter = /^([1-9]\d*|0)(\.\d{1,2})?$/;
            if (filter.test(course[N - 1]) && filter.test(course[N + 1])) {
                // 计算
                course[N].Chain = [course[N - 1], course[N + 1]];
                // 删除
                course.splice(N - 1, 1); // 删除前一个
                course.splice(N, 1);     // 删除后一个
            } else if (filter.test(course[N + 1])) {
                if (course[N - 1].Types == "Operator" && !course[N - 1].WhetherHandler) {
                    course[N].Chain = [course[N - 1], course[N + 1]];
                    course[N].Priority = 1;
                    // 删除
                    course.splice(N - 1, 1); // 删除前一个
                    course.splice(N, 1);     // 删除后一个
                } else {
                    // 计算
                    course[N] = - parseInt(course[N + 1]);
                    // 删除
                    course.splice(N + 1, 1);     // 删除后一个
                }
            } else {
                PetLog("解析错误: 运算符解析异常");
                PetLog("->解析数据:", course);
                PetLog("->解析信息:", N);
                PetLog("->报错信息: 解析参数异常");
                return false;
            }
            return true;
        };
        var manage = function (course, N) {
            course[N].Chain = [course[N - 1], course[N + 1]];
        };
        this.SetOperator("+", manage, (param) => parseInt(param[0]) + parseInt(param[1])).Priority = 1;
        this.SetOperator("*", manage, (param) => parseInt(param[0]) * parseInt(param[1])).Priority = 2;
        this.SetOperator("/", manage, (param) => parseInt(param[0]) / parseInt(param[1])).Priority = 2;
        // 运算符
        this.SetOperator(".", function (course, N) {
            var filter = /^([1-9]\d*|0)(\.\d{1,2})?$/;
            if (filter.test(course[N - 1]) && filter.test(course[N + 1])) {
                course[N] = parseFloat(course[N - 1] + "." + course[N + 1]);
                return false;
            } else {
                if (typeof course[N - 1] == "object") {
                    if (filter.test(course[N - 1].Chain[1]) && filter.test(course[N + 1])) {
                        course[N - 1].Chain[1] = parseFloat(course[N - 1].Chain[1] + "." + course[N + 1]);
                        course[N] = course[N - 1];
                    } else {
                        course[N - 1].Chain[1] = [course[N - 1].Chain[1], course[N + 1]];
                        course[N] = course[N - 1];
                    }
                } else {
                    course[N].Chain = [course[N - 1], course[N + 1]];
                }
            }
            return true;
        }).PerformProcessing = function (course, N) {
            let obj = $.VariableChain[course[0]];
            if (typeof obj != "undefined") {
                if (typeof obj[course[1]] == "undefined") {
                    obj[course[1]] = {};
                }
                // 构建传递参数
                obj = new Object(obj[course[1]]);
                Reflect.setPrototypeOf(obj, {
                    Variable: $.VariableChain[course[0]],
                    VarType: course[1],
                    Types: "Variable"
                });
                return obj;
            } else {
                PetLog("赋值错误: 异常的调用");
                PetLog("->解析数据:", course);
            }
        };
        // 赋值
        let SetVariable = new PetScript.GetResolve();
        SetVariable.Start = "=";
        SetVariable.Types = "Operator";
        SetVariable.PriorityEffectiveness = false;
        SetVariable.PerformProcessing = (param) => {
            if (param[0].Types == "Variable") {
                param[0].Variable[param[0].VarType] = param[1];
            } else if ($.VariableChain[param[0]] != undefined) {
                $.VariableChain[param[0]] = param[1];
            } else {
                PetLog("赋值错误: 赋值对象未定义");
                PetLog("->解析数据:", course);
            }
            return 0;
        };
        SetVariable.ParseHandler = function (course, N) {
            course[N].Chain = [course[N - 1]];
            // 删除前一个
            course.splice(N - 1, 1);
            // 移动后面数据
            while (course.length > N) {
                if (course[N].Types == "Marker") {
                    return true;
                }
                course[N - 1].Chain.push(course[N]);
                course.splice(N, 1);
            }
            return true;
        };
        this.ResolveList.push(SetVariable);
        // 标记符 (预处理后删除)
        this.SetStart(";");
        this.SetStart("\n", function (param, i) {
            param.splice(i, 1);
            return true;
        }).WhetherHandler = true;
        this.SetStart(" ");
        // 变量注册标记
        var Vari = this.SetStart("var", function (param, i) {
            // 构建参数
            $.VariableChain[param[i].Chain] = {};
            var Variable = {};
            Reflect.setPrototypeOf(Variable, {
                Variable: $.VariableChain,
                VarType: param[i].Chain,
                Types: "Variable"
            });
            param[i] = Variable;
        });
        Vari.ParseHandler = function (course, N) {
            course[N].Chain = course[N + 1];
            // 删除前一个
            course.splice(N + 1, 1);
        };
        Vari.WhetherHandler = true;
    },
    /**
     * 解析块
     *   将脚本按照块类定义进行解析
     */
    ParseBlock: function ($) {
        let n = $.script.length;
        let script = $.script;
        // 判断标记符
        $.JudgementMarker = function (Marker, Course) {
            var N = -1, I = -1;
            for (var i = 0; i < Marker.length; i++) {
                var n = Marker[i].Start.length;
                if (Marker[i].Start == $.script.slice($.site, $.site + n)) {
                    if (n > N) {
                        N = n;
                        I = i;
                    }
                }
            }
            // 得到标记
            if (I != -1) {
                $.site += N;
                // 解析信息
                if (Course != undefined) {
                    Reflect.setPrototypeOf(Course, Marker[I]);
                }
                return true;
            }
            return false;
        };
        // 判断结束符
        $.JudgementFinishMarker = function (Course) {
            if (Course == undefined || Course.Finish == "") {
                return false;
            } else if (Course.Finish == $.script.slice($.site, $.site + Course.Finish.length)) {
                $.site += Course.Finish.length;
                return true;
            } else {
                return false;
            }
        };
        // 解析定义类列表
        let ResolveList = this.ResolveList;
        // 递归处理
        function RecursionParse(Course) {
            let Chain = [], txt = "", N = 0;
            for (; $.site < n;) {
                let course = {};
                if ($.JudgementFinishMarker(Course)) {
                    if (N == 0) {
                        // 结束处理
                        if (txt != "") {
                            Chain.push(txt);
                        }
                        return Chain;
                    } else {
                        // 记录结束标记
                        txt += Course.Finish;
                        N -= 1;
                    }
                } else if ($.JudgementMarker(ResolveList, course)) {
                    if (Course != undefined && Course.Recursive == false) {
                        //-> 记录标记
                        txt += course.Start;
                        // 重复的结束标记
                        if (course.Finish == Course.Finish) {
                            N += 1;
                        }
                    } else if (course.Types == "Marker") {
                        // 跳过标记类型
                        if (!course.WhetherHandler) { continue; }
                        // 记录需要处理的标记符
                        if (txt != "") { Chain.push(txt); txt = ""; }
                        Chain.push(course);
                    } else if (course.Types == "Block") {
                        if (Course == undefined || Course.Recursive) {
                            // 跳过标记符
                            if (txt != "") { Chain.push(txt); txt = ""; }
                            var Marker = course;
                            Marker.Chain = RecursionParse(course);
                            Chain.push(Marker);
                        }
                    } else {
                        if (txt != "") { Chain.push(txt); txt = ""; }
                        Chain.push(course);
                    }
                    continue;
                } else {
                    txt += script[$.site];
                }
                $.site++;
            }
            if (txt != "") { Chain.push(txt); }
            return Chain;
        }
        // 开始解析
        $.Chain = RecursionParse();
    },
    /**
     * 解析运算符类型
     */
    ParseOperator: function ($) {
        // 递归解析
        function RecursionParse(course) {
            while ($.site < course.length) {
                if (typeof course[$.site] == "object") {
                    if (course[$.site + 1] != undefined && typeof course[$.site + 1] == "object") {
                        // 判断下一个的优先级与本级的优先级
                        if (course[$.site].Priority < course[$.site + 1].Priority && course[$.site].PriorityEffectiveness) {
                            // 优先处理下一个
                            $.site++;
                            if (typeof course[$.site].ParseHandler == "function" && course[$.site].WhetherHandler) {
                                // 标记当前(下一个)已经解析
                                course[$.site].WhetherHandler = false;
                                // 调用解析方法
                                if (course[$.site].ParseHandler.call($, course, $.site)) {
                                    // 递归处理 返回真就是运行递归
                                    for (let i = 0; i < course.length; i++) {
                                        if (course[i].Chain) {
                                            RecursionParse(course[i].Chain);
                                        }
                                    }
                                }
                                // 还原处理当前
                                $.site -= 2;
                                continue;
                            }
                        }
                    }
                    if (!course[$.site].WhetherHandler) {
                        $.site++;
                        continue;
                    } else if (typeof course[$.site].ParseHandler == "function" && course[$.site].WhetherHandler) {
                        // 标记当前已经解析
                        course[$.site].WhetherHandler = false;
                        // 调用解析方法
                        if (course[$.site].ParseHandler.call($, course, $.site)) {
                            var N = $.site - 1;
                            // 递归处理 返回真就是运行递归
                            for (let i = 0; i < course.length; i++) {
                                if (course[i].Chain) {
                                    $.site = 0;
                                    RecursionParse(course[i].Chain);
                                }
                            }
                            $.site = N;
                        }
                        continue;
                    } else if (course[$.site] != undefined && course[$.site].Chain != undefined) {
                        let N = $.site;
                        // 递归数据
                        $.site = 0;
                        RecursionParse(course[N].Chain);
                        $.site = N;
                    }
                }
                $.site++;
            }
        }
        // 开始解析
        RecursionParse($.Chain);
    },
    /**
     * 解析优先级
     */
    ParsePriority: function ($) {
        function RecursionParse(course) {
            if (typeof course == "object" && course.Recursive) {
                if (course.Types == "Operator" && course.Chain != undefined && course.PriorityEffectiveness) {
                    if (course.Priority > course.Chain[0].Priority) {
                        // 交换
                        let A = course.Chain[0];
                        course.Chain[0] = A.Chain[1];
                        A.Chain[1] = course;
                        // 递归
                        A.Chain[0] = RecursionParse(A.Chain[0]);
                        // 返回
                        return A;
                    }
                }
                // 递归
                if (course.Chain != undefined) {
                    // 处理其他类型
                    let site = 0;
                    while (site < course.Chain.length) {
                        course.Chain[site] = RecursionParse(course.Chain[site]);
                        site++;
                    }
                    // 第二次递归
                    course.Recursive = false;
                    course = RecursionParse(course);
                }
            }
            return course;
        }
        // 开始解析
        let site = 0;
        while (site < $.Chain.length) {
            $.Chain[site] = RecursionParse($.Chain[site]);
            site++;
        }
    },
    /**
     * 解析一层
     */
    ParsingAlayer: function (chain) {
        let i = 0;
        for (; i < chain.length; i++) {
            if (chain[i].Types == "Marker" || chain[i].Types == "Block") {
                // 递归处理
                for (var n = i + 1; n < chain.length; n++) {
                    if (chain[n].Types == "Marker") {
                        break;
                    } else if (chain[n].PerformProcessing != null) {
                        // 处理了标记
                        if (chain[n].PerformProcessing(chain, n)) {
                            break;
                        }
                    }
                }
                // 处理
                if (chain[i].PerformProcessing != null) {
                    if (chain[i].PerformProcessing(chain, i)) {
                        i--;
                    }
                }
            } else if (chain[i].Chain != undefined) {
                // 递归
                chain[i].Chain = this.ParsingAlayer(chain[i].Chain);
                // 处理
                if (chain[i].PerformProcessing != null) {
                    chain[i] = chain[i].PerformProcessing(chain[i].Chain);
                } else {
                    chain[i] = chain[i].Chain;
                }
            } else if (chain[i].PerformProcessing != null) {
                chain[i].PerformProcessing(chain, i);
            }
        }
        return chain;
    },
    /**
     * 添加运算符
     */
    SetOperator: function (symbol, call, PerformProcessing) {
        // 运算符
        let Operator = new PetScript.GetResolve();
        Operator.Start = symbol;
        Operator.Types = "Operator";
        Operator.PerformProcessing = PerformProcessing ? PerformProcessing : null;
        Operator.ParseHandler = function (course, N) {
            if (N > 0 && N < course.length - 1) {
                // 计算
                call(course, N);
                // 删除
                course.splice(N - 1, 1); // 删除前一个
                course.splice(N, 1);     // 删除后一个
                return true;
            } else {
                PetLog("解析错误: 运算符解析异常");
                PetLog("->运算符:", symbol);
                PetLog("->解析数据:", course);
                PetLog("->解析信息:", N);
                PetLog("->报错信息: 解析参数异常");
                return false;
            }
        };
        this.ResolveList.push(Operator);
        return Operator;
    },
    /**
     * 添加标记符
     */
    SetStart: function (Start, PerformProcessing) {
        let Marker = new PetScript.GetResolve();
        Marker.Start = Start;
        Marker.PerformProcessing = PerformProcessing ? PerformProcessing : null;
        Marker.WhetherHandler = false;
        Marker.Types = "Marker";
        this.ResolveList.push(Marker);
        return Marker;
    },
    /**
     * 添加范围标记
     */
    SetBlock: function (Start, Finish, ParseHandler) {
        let Block = new PetScript.GetResolve();
        Block.Start = Start;
        Block.Finish = Finish;
        Block.Types = "Block";
        Block.ParseHandler = ParseHandler ? ParseHandler : null;
        this.ResolveList.push(Block);
        return Block;
    }
};
/**
 * 得到一个解析定义类(Resolvet)
 *  解析标记:
 *    Start    开始标记 
 *    Finish   结束标记 (Operator/Marker 类型无效)
 *  解析类型:
 *    Types    属于 Block/Operator/Marker 类型
 *  优先级  
 *    Priority (Operator 有效) 优先级高的优先处理
 *  优先级生效
 *    PriorityEffectiveness
 *  递归处理
 *    Recursive  (Marker类型无效)
 *  处理函数(预处理)
 *    ParseHandler (Block类型无效)
 *  执行处理函数(最终处理)
 *    PerformProcessing 
 *  是否处理
 *    WhetherHandler
 */
PetScript.GetResolve = function () {
    this.Start = "";
    this.Finish = "";
    this.Types = "";
    this.Priority = 0;
    this.Recursive = true;
    this.PerformProcessing = null;
    this.PriorityEffectiveness = true;
    this.ParseHandler = null;
    this.WhetherHandler = true;
};
/**
 * 解析类型
 *  变量(Variable)
 *  代码块(Block)
 *  运算符(Operator)
 *  标记类型(Marker) 注: 不参与解析
 * 默认初始化定义类型
 *  Array       数组
 *  String      文本
 *  Scope       范围
 *  Block       块
 */
PetScript.Types = [
    "Variable",
    "Block",
    "Operator",
    "Marker"
];
/**
 * 调试输出
 */
var PetLog = console.warn;
